﻿module Coordinates



type Latitude = class
    val mutable private degree : int
    val mutable private minute : int
    val mutable private second : int

    member this.Degree
     with get() = this.degree
     and set((v:int)) = (this.degree <- v)

    member this.Minute
     with get() = this.minute
     and set((v:int)) = (this.minute <- v)

    member this.Second
     with get() = this.second
     and set((v:int)) = (this.second <- v)

    member x.ToDecimalDegrees = 
        let decimalSeconds = System.Convert.ToDouble(x.second)/60.00
        let decimalMinutes = (decimalSeconds + System.Convert.ToDouble(x.minute))/60.00
        let decimalHours = System.Convert.ToDouble(x.degree) + decimalMinutes

        decimalHours

    new() = { degree = 0; minute = 0; second = 0 }

    
end

type Longitude = class
    val mutable private degree : int
    val mutable private minute : int
    val mutable private second : int

    member this.Degree
     with get() = this.degree
     and set((v:int)) = (this.degree <- v)

    member this.Minute
     with get() = this.minute
     and set((v:int)) = (this.minute <- v)

    member this.Second
     with get() = this.second
     and set((v:int)) = (this.second <- v)

    member x.ToDecimalDegrees = 
        let decimalSeconds = System.Convert.ToDouble(x.second)/60.00
        let decimalMinutes = (decimalSeconds + System.Convert.ToDouble(x.minute))/60.00
        let decimalHours = System.Convert.ToDouble(x.degree) + decimalMinutes

        decimalHours

    new() = { degree = 0; minute = 0; second = 0 }
    
end

type RightAscension = class
    val mutable private hour : int
    val mutable private minute : int
    val mutable private second : int

    member this.Hour
     with get() = this.hour
     and set((v:int)) = (this.hour <- v)

    member this.Minute
     with get() = this.minute
     and set((v:int)) = (this.minute <- v)

    member this.Second
     with get() = this.second
     and set((v:int)) = (this.second <- v)

    new() = { hour = 0; minute = 0; second = 0 }
    
end

type Declination = class
    val mutable private degree : int
    val mutable private minute : int
    val mutable private second : int

    member this.Degree
     with get() = this.degree
     and set((v:int)) = (this.degree <- v)

    member this.Minute
     with get() = this.minute
     and set((v:int)) = (this.minute <- v)

    member this.Second
     with get() = this.second
     and set((v:int)) = (this.second <- v)

    new() = { degree = 0; minute = 0; second = 0 }
    
end

type Coordinate = class
    val mutable private rightAscension : RightAscension
    val mutable private declination : Declination

    member this.RightAscension
     with get() = this.rightAscension
     and set((v:RightAscension)) = (this.rightAscension <- v)

    member this.Declination
     with get() = this.declination
     and set((v:Declination)) = (this.declination <- v)

     new() = { rightAscension = new RightAscension(); declination = new Declination()}

end

type Cardinal =
    | East   = 0
    | West    = 1


let RightAscensionMinutesSecondsToDecimalRightAscension (ra:double, minute:double, second:double) =
    let decimalSeconds = System.Convert.ToDouble(second)/60.00
    let decimalMinutes = (decimalSeconds + System.Convert.ToDouble(minute))/60.00
    let decimalRA = System.Convert.ToDouble(ra) + decimalMinutes

    decimalRA

let DeclinationMinutesSecondsToDecimalDeclination (dec:double, minute:double, second:double) =
    let decimalSeconds = System.Convert.ToDouble(second)/60.00
    let decimalMinutes = (decimalSeconds + System.Convert.ToDouble(minute))/60.00
    let decimalDec = System.Convert.ToDouble(dec) + decimalMinutes

    decimalDec


let DecimalRightAscensionToHoursMinutesSeconds(input:double) =
    let mod1 = input%1.00
    let hours = input - mod1
    let decMinutes = mod1 * 60.00
    let mod2 = decMinutes%1.00
    let decSeconds = mod2 * 60.00

    let rightAscension = new RightAscension()
    rightAscension.Hour <- System.Convert.ToInt32(hours)
    rightAscension.Minute <- System.Convert.ToInt32(decMinutes)
    rightAscension.Second <- System.Convert.ToInt32(decSeconds)

    rightAscension


let DecimalDegreesToDegreesMinutesSeconds(input:double) =
    let mod1 = input%1.00
    let hours = input - mod1
    let decMinutes = mod1 * 60.00
    let mod2 = decMinutes%1.00
    let decSeconds = mod2 * 60.00

    let declination = new Declination()
    declination.Degree <- System.Convert.ToInt32(hours)
    declination.Minute <- System.Convert.ToInt32(decMinutes)
    declination.Second <- System.Convert.ToInt32(decSeconds)

    declination